package com.vpen.iot.server.handler;

import com.vpen.iot.client.handler.DelimiterEncoder;
import com.vpen.iot.server.message.v2.Message;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.springframework.stereotype.Component;

/**
 * @author: Vpen
 * date: 2023/1/18 17:01
 */
@Component
public class IotServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    private static byte[] head = {0x1f, 0x2f};
    private static byte[] tail = {0x1f, 0x3f};
    private static ByteBuf[] delimiters = new ByteBuf[]{
            Unpooled.wrappedBuffer(head),
            Unpooled.wrappedBuffer(tail)
    };


    /**
     * hello
     * <p>
     * </p>
     * 这个方法提供了一种将多个 ChannelHandler 添加到一个 ChannelPipeline 中的简便方法
     * 且一旦 Channel 被注册到了它的 EventLoop 之后，就会调用initChannel()该方法
     * 在该方法返回之后，ChannelInitializer 的实例将会从 ChannelPipeline 中移除它自己(本身他也是个ChannelHandler)
     *
     * @param ch: channel
     * @author Vpen
     * @date 2023/1/18 17:03
     */
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        // 从channel种获取pipeline
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new LoggingHandler(LogLevel.INFO));
        // out   message->byte-->加头加尾
        // 加头加尾
        pipeline.addLast(new DelimiterEncoder());
        //protobuf的编码器  byte
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        //protobuf的编码器   message
        pipeline.addLast(new ProtobufEncoder());


        // in
        //添加protobuf解码器
        // 去头去尾----> byte--->message--->业务
        pipeline.addLast("delimiter", new DelimiterBasedFrameDecoder(1024, getDelimiter()));
        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        //添加protobuf对应类解码器
//        pipeline.addLast(new ProtobufDecoder(User.UserBase.getDefaultInstance()));
        pipeline.addLast(new ProtobufDecoder(Message.MessageBase.getDefaultInstance()));

        // 添加自己的业务处理器
        pipeline.addLast("serverHandler", new IotServerHandler());
    }

    public static ByteBuf[] getDelimiter() {
        return delimiters;
    }
}
